Components.utils.import("resource://lucidity/lucidapi.jsm");

function updateKeyMenulist(menulist,defmail)
{
    try
    {
        var defkeyid = menulist.value;
        menulist.removeAllItems();
        menulist.appendItem("none","");
        var keyChain = lucidapi.getKeyChain(true);
        var usedaltdef = false;
        keyChain.forEach(function(key){
            var item = menulist.appendItem(key.getUserId(),key.getKeyId(),key.getKeyId());
            if (defmail && defmail.indexOf("@") > 0)
            {
                if (item.label.indexOf(defmail) > -1)
                {
                    menulist.selectedItem = item;
                    usedaltdef = true;
                }
            }
            else if (item.value == defkeyid)
            {
                    menulist.selectedItem = item;
                    usedaltdef = true;
            }
            if (!usedaltdef)
            {
                if (item.value == lucidapi.config.default_private_key)
                    menulist.selectedItem = item;
            }
        });
        if (menulist.selectedIndex < 0)
            menulist.selectedIndex = 0;

    } catch (e){
        Components.utils.reportError(e);
    }
}


function prepareForComparison(o) {
    if (typeof(o) == "string") {
        return o.toLowerCase();
    }
    return o;
}

var GenericTreeView = lucidapi.AbstractClass.extend(function(classref) { return {

    initialize: function(table)
    {
        classref.superClass.initialize.call(this);
        this.table = table;
//        this.rowCount = this.table.length;
    },

    getCellText: function(row, col) {
        return this.table[row][col.id.substr(col.id.lastIndexOf("-") + 1)];
    },
    getCellValue: function(row, col) {
        return this.table[row][col.id.substr(col.id.lastIndexOf("-") + 1)];
    },
    setTree: function(treebox) {
        this.treebox = treebox;
    },
    isEditable: function(row, col) {
        return col.editable;
    },
    isContainer: function(row){ return false; },
    isSeparator: function(row){ return false; },
    isSorted: function(){ return false; },
    getLevel: function(row){ return 0; },
    getImageSrc: function(row,col){ return null; },
    getRowProperties: function(row,props){},
    getCellProperties: function(row,col,props){},
    getColumnProperties: function(colid,col,props){},
    cycleHeader: function(col, elem) {}

}});

GenericTreeView.prototype.__defineGetter__("rowCount", function() { return this.table.length; } );


var KeylistTreeView = GenericTreeView.extend(function(classref) { return {

    initialize: function(table)
    {
        this.ubertable = table;
        classref.superClass.initialize.call(this,table);
        this.refreshMyData();
    },
    isContainer: function(row)
    {
        return Boolean(this.table[row]["children"]);
    },
    isContainerOpen: function(row)
    {
        return Boolean(this.table[row]["open"]);
    },
    toggleOpenState: function(row)
    {
        var rowdat = this.table[row];
        var opened = rowdat["open"] = !Boolean(rowdat["open"]);
        var changecnt = 0;
        var mytable = this.table;
        if (opened)
        {
            var children = rowdat["children"];
            children.forEach(function(childdat){
                changecnt++;
                mytable.splice(row+changecnt,0,childdat);
            });
        }
        else
        {
            var mylevel = this.getLevel(row);
            for (; changecnt + row + 1 < this.table.length; changecnt++)
            {
                if (this.getLevel(changecnt + row +1) <= mylevel)
                {
                    break;
                }
            }
            this.table.splice(row+1,changecnt);
            changecnt *= -1;
        }
        if (this.treebox)
        {
            this.treebox.rowCountChanged(row+1,changecnt);
        }
    },
    isContainerEmpty: function(row)
    {
        return Boolean(this.table[row]["children"].length < 1);
    },
    getParentIndex: function(row)
    {
        while (row > 0)
        {
            row--;
            if (this.isContainer(row))
                return row;
        }
        return -1;
    },
    getLevel: function(row){
        return this.isContainer(row) ? 0 : 1;
    },
    refreshMyData: function()
    {
        var newtable = [];
        this.ubertable.forEach(function(rowdat) {
            newtable.push(rowdat);
            if (rowdat["open"]) {
                var children = rowdat["children"];
                children.forEach(function(childdat){
                   newtable.push(childdat);
                });
            }
        })
        this.table = newtable;
        if (this.treebox)
            this.treebox.invalidate();
    },
    sortMyStuff: function(fieldName,order)
    {
        if (!order)
            order = 1;
        function columnSort(a, b) {
            try{
                var compa = prepareForComparison(a[fieldName]);
                var compb = prepareForComparison(b[fieldName]);
                if (compa > compb) return order;
                if (compa < compb) return -1 * order;
                //tie breaker: name ascending is the second level sort
                if (fieldName != ("userid")) {
                    compa = prepareForComparison(a["userid"]);
                    compa = prepareForComparison(b["userid"]);
                    if (compa > compb) return 1;
                    if (compa < compb) return -1;
                }
            } catch (e) {
                lucidapi.error(e);
            }
            return 0;
        }
        this.ubertable.sort(columnSort);
        this.refreshMyData();
    }


}});

var TreelistProtoAddons = {

    initialize: function()
    {
        var that = this;
        var tree = this.getTree();
        this.m_fullKeylistRowData = [];
        this.m_filter = "";
        if (this.id)
        {
            var treecolarr = tree.getElementsByTagNameNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul", "treecol");
            for (var ii = 0; ii < treecolarr.length; ii++)
            {
                var relid = treecolarr[ii].getAttribute("relid");
                if (!relid)
                    continue;
                treecolarr[ii].id = this.id + "-" + relid;
//                lucidapi.debug("assigning id: %s", this.id + "-" + relid);
            }
            if (!tree.hasAttribute("sortResource"))
                tree.setAttribute("sortResource", this.id + "-userid")
        }
        this.getSearchbox().addEventListener( "input", function(event) {
            that.m_filter = event.target.value.toLowerCase();
            that.rebuild();
        }, false);
    },
    getTree: function()
    {
        return document.getAnonymousNodes(this)[0];
    },
    getSearchbox: function()
    {
        return document.getAnonymousNodes(this)[2].lastChild;
    },
    rebuild: function() {
        var tree = this.getTree();
        //remember scroll position. this is useful if this is an editable table
        //to prevent the user from losing the row they edited
        var topVisibleRow = null;
        if (this.m_activeKeylistRowData) {
            topVisibleRow = tree.treeBoxObject.getFirstVisibleRow();
        }
        if (this.m_fullKeylistRowData == null) {
            //put object loading code here. for our purposes, we'll hard code it.
            this.m_fullKeylistRowData = [];
        }

        var filterstr = this.m_filter;
        if (filterstr) {
            this.m_activeKeylistRowData = this.m_fullKeylistRowData.filter(function(rowdata) {
                //we'll match on every property
                for (var rowkey in rowdata) {
                    if (prepareForComparison(rowdata[rowkey]).indexOf(filterstr) != -1) {
                        return true;
                    }
                }
                return false;
            });
        }
        else
        {
            this.m_activeKeylistRowData = this.m_fullKeylistRowData;
        }

        this.viewBackend = new KeylistTreeView(this.m_activeKeylistRowData);
        this.sortItOut();
        tree.view = this.viewBackend;
        //restore scroll position
        if (topVisibleRow) {
            tree.treeBoxObject.scrollToRow(topVisibleRow);
        }
    },
    splitterClick: function(splitter)
    {
//        lucidapi.debug("splitter [%s] clicked!",splitter.getAttribute("ordinal"));
    },
    sortItOut: function(column)
    {
        var columnName;
        var tree = this.getTree();
        var order = 1;
        //if the column is passed and it's already sorted by that column, reverse sort
        if (column) {
            columnName = column.id;
            order = column.getAttribute("sortDirection") == "ascending" ? 1 : -1;
            if (tree.getAttribute("sortResource") == columnName) {
                order *= -1;
            }
        } else {
            columnName = tree.getAttribute("sortResource");
        }


        var fieldName = columnName.substr(columnName.lastIndexOf("-") + 1);
        //setting these will make the sort option persist
    //                    tree.setAttribute("sortDirection", order == 1 ? "ascending" : "descending");
        tree.setAttribute("sortResource", columnName);
        this.viewBackend.sortMyStuff(fieldName,order);

        //set the appropriate attributes to show to indicator
        var cols = tree.getElementsByTagNameNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul","treecol");
        for (var i = 0; i < cols.length; i++) {
            cols[i].removeAttribute("sortDirection");
        }
        var colEl = document.getElementById(columnName);
        colEl.setAttribute("sortDirection", order == 1 ? "ascending" : "descending");

    },
    moveSelectedRows: function(target,rowdata)
    {
        var needrebuild = false;
        if (rowdata)
        {
            var idx = this.m_fullKeylistRowData.indexOf(rowdata);
            if (idx > -1)
            {
                target.m_fullKeylistRowData.push(rowdata);
                this.m_fullKeylistRowData.splice(idx,1);
                needrebuild = true;
            }
        }
        else
        {
            var t = this.getTree();
            var curIdx = t.currentIndex;
            var treeCols = t.columns;
            var treeView = t.view;
            var treecolel = document.getElementById(t.parentNode.id + "-" + "keyid");
            var namedCol = treeCols.getColumnFor(treecolel);
//            var namedCol = treeCols.getPrimaryColumn();
            var val = treeView.getCellText(curIdx,namedCol);
            var that = this;
            needrebuild = this.m_fullKeylistRowData.some(function(rowdata,idx){
                if (rowdata["keyid"] == val)
                {
                    target.m_fullKeylistRowData.push(rowdata);
                    that.m_fullKeylistRowData.splice(idx,1);
                    return true;
                }
            });
        }
        if (needrebuild)
        {
            this.rebuild();
            target.rebuild();
        }
    },
    getFullRowData: function()
    {
        return this.m_fullKeylistRowData.concat();
    }
}

function updateGenericBox(keyBox,secret)
{
    var keyChain = lucidapi.getKeyChain(secret);
    var mydata = keyBox.m_fullKeylistRowData = [];
    keyChain.forEach(function(subval){
        var mkeydat = {
            userid: subval.getUserId(),
            keyid: subval.getKeyId(),
            created: subval.getCreatedStamp(),
            expires: subval.getExpirationStamp(),
            keysize: subval.getKeySize(),
            children: []
        };
        mydata.push(mkeydat);
        subval.getSubKeys().forEach(function(subsub){
            mkeydat.children.push({
                userid: "subkey",
                keyid: subsub.getKeyId(),
                created: subsub.getCreatedStamp(),
                expires: subsub.getExpirationStamp(),
                keysize: subsub.getKeySize(),
                parent: subval.getKeyId()
            });
        });
    });
    keyBox.rebuild();

}


